Widget 類別的原始碼上有標注 @immutable,這個標注的意思是不可變的;簡單的來說這個類別裡的類別屬性必需宣告成 final,經賦值後就不可改變。
@immutable
abstract class Widget extends DiagnosticableTree {
  /// Initializes [key] for subclasses.
  const Widget({ this.key });
  ...
在先前的範例中,我們有使用過 StatelessWidget,這類型的控件通常只需要定義佈局內容,而 StatefulWidget 內部使用 State 來處理狀態變化的管理,可以在收到異動後透過 setState 通知 Flutter 重新渲染畫面。
Widget 在設計上是 immutable 的,也就是說控件在經過創建後就不能夠修改,所以 Flutter 設計上將狀態管理的這件事情交由 State 類別來處理。
繼承 StatefulWidget 的控件需要覆寫掉 createState 這個方式,回傳自己定義的 State 對象,在 State 中,我們可以定義想要的屬性,並且定義控件 build 方法,這個方法與 StatelessWidget 的 build 行為一樣是用來定義佈局的內容。
StatefulWidget 的實作可以參考下面時間控件的寫法,在狀態中我們有個字串類別的 _now 屬性用來顯示目前的時間。TimeModel 類別 mixin ChangeNotifier,每隔一秒鐘就會觸發時間變更的事件。
我們在生命週期階段的 initState 監聽時間變更的事件,並在收到事件後更新_now的資料並呼叫setState更新畫面。
class Clock extends StatefulWidget {
  // 這邊的 key 是底層 widget canUpdate 方法有關
  const Clock({Key? key}) : super(key: key);
  @override
  _Clock createState() => _Clock();
}
class _Clock extends State<Clock> {
  // TimeModel 自己實作的時間類別
  // 此類別 mixin ChangeNotifier 類別,提供`觀察者模式`的特性
  final TimeModel time = TimeModel();
  String _now = "";
   // 透過呼叫 setState 通知狀態已異動
  _updateTime() {
    setState(() {
      _now = time.toString();
    });
  }
  // State 生命週期
  @override
  void initState() {
    print('====initState===');
    super.initState();
    // 監聽事件
    time.addListener(_updateTime);
  }
  @override
  Widget build(BuildContext context) {
    print('====build====');
    return Text(_now);
  }
}
今日成果

重點回顧:
StatelessWidget 和 StatefulWidget 兩種。StatefulWidget,並定義 State 物件。setState 通知 widget